package com.foreverwin.jzymes.websocket;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foreverwin.jzymes.common.mapper.DashBoardAdviceMapper;
import com.foreverwin.jzymes.common.mapper.SfcBatchPassLogAdviceMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.framework.annotation.WebSocketHandler;
import com.foreverwin.jzymes.framework.event.AppEvent;
import com.foreverwin.jzymes.framework.websocket.TextMessageWebSocketWraper;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.*;

@WebSocketHandler(channel = "Z_DB_ALL_EQU_OEE")
public class AllEquipOEEHandler extends TextMessageWebSocketWraper {

    @Autowired
    IActivityRuleAdviceService activityRuleAdviceService;
    @Autowired
    IItemGroupAdviceService itemGroupAdviceService;
    @Autowired
    ICustomFieldsAdviceService customFieldsAdviceService;
    @Autowired
    ICommonService commonService;
    @Autowired
    IProductionShiftService productionShiftService;
    @Autowired
    IResourceAdviceService resourceAdviceService;
    @Autowired
    DashBoardAdviceMapper dashBoardAdviceMapper;
    @Autowired
    SfcBatchPassLogAdviceMapper sfcBatchPassLogAdviceMapper;

    private Map<String,String> activityRuleMap;

    public AllEquipOEEHandler(){
        events = new ArrayList();
        events.add( "RESOURCE_STATUS_CHANGE" );
    }

    @Override
    public void doAfterOpen(Connection connection) {
        activityRuleMap = activityRuleAdviceService.findActivityRules( getChannel() );
    }

    @Override
    public void doAfterClose() {

    }

    @Override
    public JSONObject doReceiveAndReply(String messageType, JSONObject requestParams) {
        if( "WS_INIT_DATA".equals( messageType ) ){
            buildAllEquipOeeData();
        }
        return null;
    }

    @Override
    public void onAppEvent(AppEvent<?> appEvent) {
        String event = appEvent.getName();
        JSONObject eventData = (JSONObject) appEvent.getData();

        if( "RESOURCE_STATUS_CHANGE".equals( event ) ){
            String site = eventData.getString( "SITE" );
            String resrce = eventData.getString( "RESRCE" );
            String status = eventData.getString( "STATUS" );

            JSONObject cnc = new JSONObject();
            cnc.put( "id", resrce );
            cnc.put("status", status );
            JSONArray cncs = new JSONArray();
            cncs.add( cnc );
            JSONObject response = new JSONObject();
            response.put( "cncs", cncs );
            sendMessage( "WS_RESOURCE_STATUS", response );
        }
    }

    /**
     * 统计每班cnc设备稼动率
     * 计划运行时间和实际运行时间均以分钟为单位
     *
     */
    public void buildAllEquipOeeData(){
        String site = activityRuleMap.get( "SITE" );
        String resourceType = activityRuleMap.get( "RESOURCE_TYPE" );
        int planEquip = Integer.valueOf( activityRuleMap.get( "PLAN_EQUIP" ) );
        List statusList = Arrays.asList( activityRuleMap.get( "STATUS_LIST" ).split(",") );
        String oeeStatus = activityRuleMap.get( "OEE_STATUS" );
        String downStatus = activityRuleMap.get( "DOWN_STATUS" );
        String defaultStatus = activityRuleMap.get( "DEFAULT_STATUS" );

        Date now = new Date();
        int timeUnit = 60 * 1000;
        Date[] dateRange = productionShiftService.findShiftRange( site, now );
        Long planRunTime = ( dateRange[1].getTime() - dateRange[0].getTime() ) / timeUnit * planEquip;

        JSONArray cncs = new JSONArray();
        List<Map<String,Object>> cncList = resourceAdviceService.findResourceListByCncType(  site, null, resourceType );
        for( Map<String,Object> map : cncList ) {
            String resource = (String) map.get("RESRCE");
            String status = resourceAdviceService.findResourceStatus( site, resource );
            if( !statusList.contains( status ) ){
                status = defaultStatus;
            }

            JSONObject cnc = new JSONObject();
            cnc.put( "id", resource );
            cnc.put("status", status );
            cncs.add( cnc );
        }

        JSONArray statusRateList = new JSONArray();
        JSONObject statusRateMap = new JSONObject();

        JSONObject defaultStatusRate = new JSONObject();
        defaultStatusRate.put( "id", defaultStatus );
        defaultStatusRate.put( "qty", planRunTime );
        defaultStatusRate.put( "rate", BigDecimal.ONE );
        statusRateMap.put( defaultStatus, defaultStatusRate );
        statusRateList.add( defaultStatusRate );

        List<Map<String,Object>> resourceTimeSummaryList = dashBoardAdviceMapper.countResourceTimeSummary( site, dateRange[0], dateRange[1] );
        for( Map<String,Object> resourceTimeSummary : resourceTimeSummaryList ){
            String status = (String) resourceTimeSummary.get( "STATUS" );
            Long runTime = ((BigDecimal)resourceTimeSummary.get( "ELAPSED_TIME" )).longValue();

            if( !statusList.contains( status ) ){
                continue;
            }

            JSONObject statusRate = null;
            if( statusRateMap.containsKey( status ) ){
                statusRate = statusRateMap.getJSONObject( status );
            }else{
                statusRate = new JSONObject();
                statusRate.put( "id", status );
                statusRate.put( "qty", 0L );
                statusRate.put( "rate", "" );
                statusRateMap.put( status, statusRate );
                statusRateList.add( statusRate );
            }


            statusRate.put( "qty", statusRate.getLong( "qty" ) + runTime );
            statusRate.put( "rate", BigDecimal.valueOf( statusRate.getLong( "qty" ) ).divide( BigDecimal.valueOf( planRunTime ), 4, BigDecimal.ROUND_HALF_UP ) );
            defaultStatusRate.put( "qty", defaultStatusRate.getLong( "qty" ) - statusRate.getLong( "qty" ) );
            defaultStatusRate.put( "rate", defaultStatusRate.getBigDecimal("rate").subtract( statusRate.getBigDecimal( "rate" ) ) );
        }

        JSONObject response = new JSONObject();
        response.put( "planEquip", planEquip );
        response.put( "oeeRate", statusRateMap.getJSONObject( oeeStatus ) != null ? String.format( "%.2f%%", statusRateMap.getJSONObject( oeeStatus ) .getBigDecimal("rate").multiply( BigDecimal.valueOf( 100 ) ) ) : "0%" );
        response.put( "faultRate", statusRateMap.getJSONObject( downStatus ) != null ? String.format( "%.2f%%", statusRateMap.getJSONObject( downStatus ).getBigDecimal("rate").multiply( BigDecimal.valueOf( 100 ) ) ) : "0%" );
        response.put( "statusRate", statusRateList );
        response.put( "cncs", cncs );
        sendMessage( response );
    }

}
